home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / filesys / .#emul_handler.c.1.8 next >
Text File  |  1996-09-13  |  17KB  |  708 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: emul_handler.c,v 1.8 1996/09/11 16:54:24 digulla Exp $
  4.     $Log: emul_handler.c,v $
  5.     Revision 1.8  1996/09/11 16:54:24  digulla
  6.     Always use __AROS_SLIB_ENTRY() to access shared external symbols, because
  7.     some systems name an external symbol "x" as "_x" and others as "x".
  8.     (The problem arises with assembler symbols which might differ)
  9.  
  10.     Revision 1.7  1996/09/11 14:40:10  digulla
  11.     Integrated patch by I. Templeton: Under FreeBSD, there is a clash with
  12.     struct timeval
  13.  
  14.     Revision 1.6  1996/09/11 13:05:34  digulla
  15.     Own function to open a file (M. Fleischer)
  16.  
  17.     Revision 1.5  1996/08/31 12:58:11  aros
  18.     Merged in/modified for FreeBSD.
  19.  
  20.     Revision 1.4  1996/08/30 17:02:06  digulla
  21.     Fixed a bug which caused the shell to exit if the timer sent a signal. This
  22.     fix is a very bad hack :(
  23.  
  24.     Revision 1.3  1996/08/13 15:35:07  digulla
  25.     Replaced __AROS_LA by __AROS_LHA
  26.  
  27.     Revision 1.2  1996/08/01 17:41:22  digulla
  28.     Added standard header for all files
  29.  
  30.     Desc:
  31.     Lang:
  32. */
  33. #include <exec/resident.h>
  34. #include <exec/memory.h>
  35. #include <clib/exec_protos.h>
  36. #include <utility/tagitem.h>
  37. #include <dos/dosextens.h>
  38. #include <dos/filesystem.h>
  39. #include <dos/exall.h>
  40. #include <dos/dosasl.h>
  41. #include <clib/dos_protos.h>
  42. #include <aros/libcall.h>
  43. #include <unistd.h>
  44. #include <fcntl.h>
  45. #include <dirent.h>
  46. #include <string.h>
  47. #include <stdlib.h>
  48. #include <errno.h>
  49. #if defined(FreeBSD)
  50. #define timeval _timeval
  51. #include <sys/stat.h>
  52. #define tv_sec tv_secs
  53. #define tv_usec tv_micros
  54. #undef timeval
  55. #else
  56. #include <sys/stat.h>
  57. #endif
  58. #ifdef __GNUC__
  59.     #include "emul_handler_gcc.h"
  60. #endif
  61.  
  62. static const char name[];
  63. static const char version[];
  64. static const APTR inittabl[4];
  65. static void *const functable[];
  66. static const UBYTE datatable;
  67.  
  68. struct emulbase * __AROS_SLIB_ENTRY(init,emul_handler) ();
  69. void __AROS_SLIB_ENTRY(open,emul_handler) ();
  70. BPTR __AROS_SLIB_ENTRY(close,emul_handler) ();
  71. BPTR __AROS_SLIB_ENTRY(expunge,emul_handler) ();
  72. int __AROS_SLIB_ENTRY(null,emul_handler) ();
  73. void __AROS_SLIB_ENTRY(beginio,emul_handler) ();
  74. LONG __AROS_SLIB_ENTRY(abortio,emul_handler) ();
  75.  
  76. static const char end;
  77.  
  78. struct filehandle
  79. {
  80.     char *name;
  81.     int type;
  82.     long fd;
  83. };
  84. #define FHD_FILE    0
  85. #define FHD_DIRECTORY    1
  86.  
  87. int emul_handler_entry(void)
  88. {
  89.     /* If the device was executed by accident return error code. */
  90.     return -1;
  91. }
  92.  
  93. const struct Resident emul_handler_resident=
  94. {
  95.     RTC_MATCHWORD,
  96.     (struct Resident *)&emul_handler_resident,
  97.     (APTR)&end,
  98.     RTF_AUTOINIT,
  99.     1,
  100.     NT_LIBRARY,
  101.     0,
  102.     (char *)name,
  103.     (char *)&version[6],
  104.     (ULONG *)inittabl
  105. };
  106.  
  107. static const char name[]="emul.handler";
  108.  
  109. static const char version[]="$VER: emul_handler 1.0 (28.3.96)\n\015";
  110.  
  111. static const APTR inittabl[4]=
  112. {
  113.     (APTR)sizeof(struct emulbase),
  114.     (APTR)functable,
  115.     (APTR)&datatable,
  116.     &__AROS_SLIB_ENTRY(init,emul_handler)
  117. };
  118.  
  119. static void *const functable[]=
  120. {
  121.     &__AROS_SLIB_ENTRY(open,emul_handler),
  122.     &__AROS_SLIB_ENTRY(close,emul_handler),
  123.     &__AROS_SLIB_ENTRY(expunge,emul_handler),
  124.     &__AROS_SLIB_ENTRY(null,emul_handler),
  125.     &__AROS_SLIB_ENTRY(beginio,emul_handler),
  126.     &__AROS_SLIB_ENTRY(abortio,emul_handler),
  127.     (void *)-1
  128. };
  129.  
  130. static const UBYTE datatable=0;
  131.  
  132. LONG u2a[][2]=
  133. {
  134.   { ENOMEM, ERROR_NO_FREE_STORE },
  135.   { ENOENT, ERROR_OBJECT_NOT_FOUND },
  136.   { EINTR,  -1 }, /*ada 30.8.96 This is a REALLY BAD hack !! */
  137.   { 0, 0 }
  138. };
  139.  
  140. LONG err_u2a(void)
  141. {
  142.     ULONG i;
  143.     for(i=0;i<sizeof(u2a)/sizeof(u2a[0]);i++)
  144.     if(u2a[i][0]==errno)
  145.         break;
  146.     return u2a[i][1];
  147. }
  148.  
  149. static void shrink(char *filename)
  150. {
  151.     char *s1,*s2;
  152.     unsigned long len;
  153.     for(;;)
  154.     {
  155.     while(*filename=='/')
  156.         memmove(filename,filename+1,strlen(filename));
  157.     s1=strstr(filename,"//");
  158.     if(s1==NULL)
  159.         break;
  160.     s2=s1;
  161.     while(s2>filename&&*--s2!='/')
  162.         ;
  163.     memmove(s2,s1+2,strlen(s1+1));
  164.     }
  165.     len=strlen(filename);
  166.     if(len&&filename[len-1]=='/')
  167.     filename[len-1]=0;
  168. }
  169.  
  170. static LONG open_(struct filehandle **handle,STRPTR name,LONG mode)
  171. {
  172.     LONG ret=ERROR_NO_FREE_STORE;
  173.     struct filehandle *fh;
  174.     struct stat st;
  175.     long flags;
  176.     fh=(struct filehandle *)malloc(sizeof(struct filehandle));
  177.     if(fh!=NULL)
  178.     {
  179.     if(!*name&&(*handle)->type==FHD_FILE&&((*handle)->fd==STDIN_FILENO||
  180.        (*handle)->fd==STDOUT_FILENO||(*handle)->fd==STDERR_FILENO))
  181.     {
  182.         fh->type=FHD_FILE;
  183.         fh->fd=(*handle)->fd;
  184.         fh->name="";
  185.         *handle=fh;
  186.         return 0;
  187.     }
  188.     fh->name=(char *)malloc(strlen((*handle)->name)+strlen(name)+2);
  189.     if(fh->name!=NULL)
  190.     {
  191.         strcpy(fh->name,(*handle)->name);
  192.         strcat(fh->name,"/");
  193.         strcat(fh->name,name);
  194.         shrink(fh->name);
  195.         if(!stat(*fh->name?fh->name:".",&st))
  196.         {
  197.         if(S_ISREG(st.st_mode))
  198.         {
  199.             fh->type=FHD_FILE;
  200.             flags=(mode&FMF_CREATE?O_CREAT:0)|
  201.               (mode&FMF_CLEAR?O_TRUNC:0);
  202.             if(mode&FMF_WRITE)
  203.             flags|=mode&FMF_READ?O_RDWR:O_WRONLY;
  204.             else
  205.             flags|=O_RDONLY;
  206.             fh->fd=open(*fh->name?fh->name:".",flags,0770);
  207.             if(fh->fd>=0)
  208.             {
  209.             *handle=fh;
  210.             return 0;
  211.             }
  212.         }else if(S_ISDIR(st.st_mode))
  213.         {
  214.             fh->type=FHD_DIRECTORY;
  215.             fh->fd=(long)opendir(*fh->name?fh->name:".");
  216.             if(fh->fd)
  217.             {
  218.             *handle=fh;
  219.             return 0;
  220.             }
  221.         }else
  222.             errno=ENOENT;
  223.         }
  224.         ret=err_u2a();
  225.         free(fh->name);
  226.     }
  227.     free(fh);
  228.     }
  229.     return ret;
  230. }
  231.  
  232. static LONG open_file(struct filehandle **handle,STRPTR name,LONG mode,LONG protect)
  233. {
  234.     LONG ret=ERROR_NO_FREE_STORE;
  235.     struct filehandle *fh;
  236.     long flags;
  237.     fh=(struct filehandle *)malloc(sizeof(struct filehandle));
  238.     if(fh!=NULL)
  239.     {
  240.     if(!*name&&(*handle)->type==FHD_FILE&&((*handle)->fd==STDIN_FILENO||
  241.        (*handle)->fd==STDOUT_FILENO||(*handle)->fd==STDERR_FILENO))
  242.     {
  243.         fh->type=FHD_FILE;
  244.         fh->fd=(*handle)->fd;
  245.         fh->name="";
  246.         *handle=fh;
  247.         return 0;
  248.     }
  249.     fh->name=(char *)malloc(strlen((*handle)->name)+strlen(name)+2);
  250.     if(fh->name!=NULL)
  251.     {
  252.         strcpy(fh->name,(*handle)->name);
  253.         strcat(fh->name,"/");
  254.         strcat(fh->name,name);
  255.         shrink(fh->name);
  256.         fh->type=FHD_FILE;
  257.         flags=(mode&FMF_CREATE?O_CREAT:0)|
  258.           (mode&FMF_CLEAR?O_TRUNC:0);
  259.         if(mode&FMF_WRITE)
  260.         flags|=mode&FMF_READ?O_RDWR:O_WRONLY;
  261.         else
  262.         flags|=O_RDONLY;
  263.         fh->fd=open(fh->name,flags,0770);
  264.         if(fh->fd>=0)
  265.         {
  266.         *handle=fh;
  267.         return 0;
  268.         }
  269.         ret=err_u2a();
  270.         free(fh->name);
  271.     }
  272.     free(fh);
  273.     }
  274.     return ret;
  275. }
  276.  
  277. static LONG free_lock(struct filehandle *current)
  278. {
  279.     switch(current->type)
  280.     {
  281.     case FHD_FILE:
  282.         if(current->fd!=STDIN_FILENO&¤t->fd!=STDOUT_FILENO&&
  283.            current->fd!=STDERR_FILENO)
  284.         {
  285.         close(current->fd);
  286.         free(current->name);
  287.         }
  288.         break;
  289.     case FHD_DIRECTORY:
  290.         closedir((DIR *)current->fd);
  291.         free(current->name);
  292.         break;
  293.     }
  294.     free(current);
  295.     return 0;
  296. }
  297.  
  298. static LONG startup(struct emulbase *emulbase)
  299. {
  300.     struct filehandle *fhi, *fho, *fhe, *fhv, *fhc, *fhs;
  301.     struct DosList *dlv, *dlc;
  302.     static struct filehandle sys={ "", FHD_DIRECTORY, 0 };
  303.     LONG ret=ERROR_NO_FREE_STORE;
  304.  
  305.     fhi=(struct filehandle *)malloc(sizeof(struct filehandle));
  306.     if(fhi!=NULL)
  307.     {
  308.     fho=(struct filehandle *)malloc(sizeof(struct filehandle));
  309.     if(fho!=NULL)
  310.     {
  311.         fhe=(struct filehandle *)malloc(sizeof(struct filehandle));
  312.         if(fhe!=NULL)
  313.         {
  314.         fhv=&sys;
  315.         ret=open_(&fhv,"",0);
  316.         if(!ret)
  317.         {
  318.             fhc=&sys;
  319.             ret=open_(&fhc,"",0);
  320.             if(!ret)
  321.             {
  322.             fhs=&sys;
  323.             ret=open_(&fhs,"",0);
  324.             if(!ret)
  325.             {
  326.                 ret=ERROR_NO_FREE_STORE;
  327.                 dlv=MakeDosEntry("Workbench",DLT_VOLUME);
  328.                 if(dlv!=NULL)
  329.                 {
  330.                 dlc=MakeDosEntry("SYS",DLT_DEVICE);
  331.                 if(dlc!=NULL)
  332.                 {
  333.                     ret=ERROR_OBJECT_EXISTS;
  334.                     dlv->dol_Unit  =(struct Unit *)fhv;
  335.                     dlv->dol_Device=&emulbase->device;
  336.                     dlc->dol_Unit  =(struct Unit *)fhc;
  337.                     dlc->dol_Device=&emulbase->device;
  338.                     fhi->type=FHD_FILE;
  339.                     fhi->fd=STDIN_FILENO;
  340.                     fhi->name="";
  341.                     emulbase->stdin=(struct Unit *)fhi;
  342.                     fho->type=FHD_FILE;
  343.                     fho->fd=STDOUT_FILENO;
  344.                     fho->name="";
  345.                     emulbase->stdout=(struct Unit *)fho;
  346.                     fhe->type=FHD_FILE;
  347.                     fhe->fd=STDERR_FILENO;
  348.                     fhe->name="";
  349.                     emulbase->stderr=(struct Unit *)fhe;
  350.                     if(AddDosEntry(dlv))
  351.                     {
  352.                     if(AddDosEntry(dlc))
  353.                     {
  354.                         DOSBase->dl_NulHandler=&emulbase->device;
  355.                         DOSBase->dl_NulLock   =(struct Unit *)fhs;
  356.                         return 0;
  357.                     }
  358.                     RemDosEntry(dlv);
  359.                     }
  360.                     FreeDosEntry(dlc);
  361.                 }
  362.                 FreeDosEntry(dlv);
  363.                 }
  364.                 free_lock(fhs);
  365.             }
  366.             free_lock(fhc);
  367.             }
  368.             free_lock(fhv);
  369.         }
  370.         free(fhe);
  371.         }
  372.         free(fho);
  373.     }
  374.     free(fhi);
  375.     }
  376.     return ret;
  377. }
  378.  
  379. static const ULONG sizes[]=
  380. { 0, offsetof(struct ExAllData,ed_Type), offsetof(struct ExAllData,ed_Size),
  381.   offsetof(struct ExAllData,ed_Prot), offsetof(struct ExAllData,ed_Days),
  382.   offsetof(struct ExAllData,ed_Comment), offsetof(struct ExAllData,ed_OwnerUID),
  383.   sizeof(struct ExAllData) };
  384.  
  385. static LONG examine(struct filehandle *fh,struct ExAllData *ead,ULONG size,ULONG type)
  386. {
  387.     STRPTR next, end, last, name;
  388.     struct stat st;
  389.     if(type>ED_OWNER)
  390.     return ERROR_BAD_NUMBER;
  391.     next=(STRPTR)ead+sizes[type];
  392.     end =(STRPTR)ead+size;
  393.     if(next>=end)
  394.     return ERROR_BUFFER_OVERFLOW;
  395.     if(lstat(*fh->name?fh->name:".",&st))
  396.     return err_u2a();
  397.     switch(type)
  398.     {
  399.     default:
  400.     case ED_OWNER:
  401.         ead->ed_OwnerUID=st.st_uid;
  402.         ead->ed_OwnerGID=st.st_gid;
  403.     case ED_COMMENT:
  404.         ead->ed_Comment=NULL;
  405.     case ED_DATE:
  406.         ead->ed_Days=st.st_ctime/(60*60*24)-(6*365+2*366);
  407.         ead->ed_Mins=(st.st_ctime/60)%(60*24);
  408.         ead->ed_Ticks=(st.st_ctime%60)*TICKS_PER_SECOND;
  409.     case ED_PROTECTION:
  410.         ead->ed_Prot=(st.st_mode&S_IRUSR?FIBF_READ:0)|
  411.              (st.st_mode&S_IWUSR?FIBF_WRITE:0)|
  412.              (st.st_mode&S_IXUSR?FIBF_EXECUTE:0)|
  413.              FIBF_SCRIPT|FIBF_DELETE;
  414.     case ED_SIZE:
  415.         ead->ed_Size=st.st_size;
  416.     case ED_TYPE:
  417.         ead->ed_Type=S_ISREG(st.st_mode)?ST_FILE:
  418.              S_ISDIR(st.st_mode)?(*fh->name?ST_USERDIR:ST_ROOT):0;
  419.     case ED_NAME:
  420.         ead->ed_Name=next;
  421.         last=name=*fh->name?fh->name:"Workbench";
  422.         while(*name)
  423.         if(*name++=='/')
  424.             last=name;
  425.         for(;;)
  426.         {
  427.         if(next>=end)
  428.             return ERROR_BUFFER_OVERFLOW;
  429.         if(!(*next++=*last++))
  430.             break;
  431.         }
  432.     case 0:
  433.         ead->ed_Next=(struct ExAllData *)(((IPTR)next+PTRALIGN-1)&~(PTRALIGN-1));
  434.         return 0;
  435.     }
  436. }
  437.  
  438. static LONG examine_all(struct filehandle *fh,struct ExAllData *ead,ULONG size,ULONG type)
  439. {
  440.     struct ExAllData *last=NULL;
  441.     STRPTR end=(STRPTR)ead+size, name, old;
  442.     off_t oldpos;
  443.     struct dirent *dir;
  444.     LONG error;
  445.     if(fh->type!=FHD_DIRECTORY)
  446.     return ERROR_OBJECT_WRONG_TYPE;
  447.     for(;;)
  448.     {
  449.     oldpos=telldir((DIR *)fh->fd);
  450.     errno=0;
  451.     dir=readdir((DIR *)fh->fd);
  452.     if(dir==NULL)
  453.     {
  454.         error=err_u2a();
  455.         break;
  456.     }
  457.     if(dir->d_name[0]=='.'&&(!dir->d_name[1]||(dir->d_name[1]=='.'&&!dir->d_name[2])))
  458.         continue;
  459.     name=(STRPTR)malloc(strlen(fh->name)+strlen(dir->d_name)+2);
  460.     if(name==NULL)
  461.     {
  462.         error=ERROR_NO_FREE_STORE;
  463.         break;
  464.     }
  465.     strcpy(name,fh->name);
  466.     if(*name)
  467.         strcat(name,"/");
  468.     strcat(name,dir->d_name);
  469.     old=fh->name;
  470.     fh->name=name;
  471.     error=examine(fh,ead,end-(STRPTR)ead,type);
  472.     fh->name=old;
  473.     free(name);
  474.     if(error)
  475.         break;
  476.     last=ead;
  477.     ead=ead->ed_Next;
  478.     }
  479.     if((!error||error==ERROR_BUFFER_OVERFLOW)&&last!=NULL)
  480.     {
  481.     last->ed_Next=NULL;
  482.     seekdir((DIR *)fh->fd,oldpos);
  483.     return 0;
  484.     }
  485.     if(!error)
  486.     error=ERROR_NO_MORE_ENTRIES;
  487.     rewinddir((DIR *)fh->fd);
  488.     return error;
  489. }
  490.  
  491. __AROS_LH2(struct emulbase *, init,
  492.  __AROS_LHA(struct emulbase *, emulbase, D0),
  493.  __AROS_LHA(BPTR,              segList,   A0),
  494.        struct ExecBase *, sysBase, 0, emul_handler)
  495. {
  496.     __AROS_FUNC_INIT
  497.  
  498.     /* Store arguments */
  499.     emulbase->sysbase=sysBase;
  500.     emulbase->seglist=segList;
  501.     emulbase->device.dd_Library.lib_OpenCnt=1;
  502.     emulbase->dosbase=(struct DosLibrary *)OpenLibrary("dos.library",39);
  503.     if(emulbase->dosbase!=NULL)
  504.     {
  505.     if(AttemptLockDosList(LDF_ALL|LDF_WRITE))
  506.     {
  507.         if(!startup(emulbase))
  508.         {
  509.         UnLockDosList(LDF_ALL|LDF_WRITE);
  510.         return emulbase;
  511.         }
  512.         UnLockDosList(LDF_ALL|LDF_WRITE);
  513.     }
  514.     CloseLibrary((struct Library *)emulbase->dosbase);
  515.     }
  516.  
  517.     return NULL;
  518.     __AROS_FUNC_EXIT
  519. }
  520.  
  521. __AROS_LH3(void, open,
  522.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  523.  __AROS_LHA(ULONG,              unitnum, D0),
  524.  __AROS_LHA(ULONG,              flags, D0),
  525.        struct emulbase *, emulbase, 1, emul_handler)
  526. {
  527.     __AROS_FUNC_INIT
  528.  
  529.     /* Keep compiler happy */
  530.     unitnum=0;
  531.     flags=0;
  532.  
  533.     /* I have one more opener. */
  534.     emulbase->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  535.  
  536.     /* Set returncode */
  537.     iofs->IOFS.io_Error=0;
  538.  
  539.     /* Mark Message as recently used. */
  540.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  541.     __AROS_FUNC_EXIT
  542. }
  543.  
  544. __AROS_LH1(BPTR, close,
  545.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  546.        struct emulbase *, emulbase, 2, emul_handler)
  547. {
  548.     __AROS_FUNC_INIT
  549.  
  550.     /* Let any following attemps to use the device crash hard. */
  551.     iofs->IOFS.io_Device=(struct Device *)-1;
  552.     return 0;
  553.     __AROS_FUNC_EXIT
  554. }
  555.  
  556. __AROS_LH0(BPTR, expunge, struct emulbase *, emulbase, 3, emul_handler)
  557. {
  558.     __AROS_FUNC_INIT
  559.  
  560.     /* Do not expunge the device. Set the delayed expunge flag and return. */
  561.     emulbase->device.dd_Library.lib_Flags|=LIBF_DELEXP;
  562.     return 0;
  563.     __AROS_FUNC_EXIT
  564. }
  565.  
  566. __AROS_LH0I(int, null, struct emulbase *, emulbase, 4, emul_handler)
  567. {
  568.     __AROS_FUNC_INIT
  569.     return 0;
  570.     __AROS_FUNC_EXIT
  571. }
  572.  
  573. __AROS_LH1(void, beginio,
  574.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  575.        struct emulbase *, emulbase, 5, emul_handler)
  576. {
  577.     __AROS_FUNC_INIT
  578.     LONG error=0;
  579.  
  580.     /* WaitIO will look into this */
  581.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  582.  
  583.     /*
  584.     Do everything quick no matter what. This is possible
  585.     because I never need to Wait().
  586.     */
  587.     switch(iofs->IOFS.io_Command)
  588.     {
  589.     case FSA_OPEN:
  590.         error=open_((struct filehandle **)&iofs->IOFS.io_Unit,
  591.              (char *)iofs->io_Args[0],iofs->io_Args[1]);
  592.         break;
  593.  
  594.     case FSA_OPEN_FILE:
  595.         error=open_file((struct filehandle **)&iofs->IOFS.io_Unit,
  596.              (char *)iofs->io_Args[0],
  597.              iofs->io_Args[1],iofs->io_Args[2]);
  598.         break;
  599.  
  600.     case FSA_CLOSE:
  601.         error=free_lock((struct filehandle *)iofs->IOFS.io_Unit);
  602.         break;
  603.  
  604.     case FSA_IS_INTERACTIVE:
  605.     {
  606.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  607.         if(fh->type==FHD_FILE)
  608.         iofs->io_Args[0]=isatty(fh->fd);
  609.         else
  610.         iofs->io_Args[0]=0;
  611.         break;
  612.     }
  613.  
  614.     case FSA_READ:
  615.     {
  616.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  617.         if(fh->type==FHD_FILE)
  618.         {
  619.         if(fh->fd==STDOUT_FILENO)
  620.             fh->fd=STDIN_FILENO;
  621.         iofs->io_Args[1]=read(fh->fd,(APTR)iofs->io_Args[0],iofs->io_Args[1]);
  622.         if(iofs->io_Args[1]<0)
  623.             error=err_u2a();
  624.         }else
  625.         error=ERROR_OBJECT_WRONG_TYPE;
  626.         break;
  627.     }
  628.  
  629.     case FSA_WRITE:
  630.     {
  631.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  632.         if(fh->type==FHD_FILE)
  633.         {
  634.         if(fh->fd==STDIN_FILENO)
  635.             fh->fd=STDOUT_FILENO;
  636.         iofs->io_Args[1]=write(fh->fd,(APTR)iofs->io_Args[0],iofs->io_Args[1]);
  637.         if(iofs->io_Args[1]<0)
  638.             error=err_u2a();
  639.         }else
  640.         error=ERROR_OBJECT_WRONG_TYPE;
  641.         break;
  642.     }
  643.  
  644.     case FSA_SEEK:
  645.     {
  646.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  647.         LONG mode=iofs->io_Args[2];
  648.         LONG oldpos;
  649.         if(fh->type==FHD_FILE)
  650.         {
  651.         oldpos=lseek(fh->fd,0,SEEK_CUR);
  652.         if(lseek(fh->fd,iofs->io_Args[1],mode==OFFSET_BEGINNING?SEEK_SET:mode==OFFSET_CURRENT?SEEK_CUR:SEEK_END)<0)
  653.             error=err_u2a();
  654.         iofs->io_Args[0]=0;
  655.         iofs->io_Args[1]=oldpos;
  656.         }else
  657.         error=ERROR_OBJECT_WRONG_TYPE;
  658.         break;
  659.     }
  660.  
  661.     case FSA_EXAMINE:
  662.         error=examine((struct filehandle *)iofs->IOFS.io_Unit,
  663.               (struct ExAllData *)iofs->io_Args[0],
  664.               iofs->io_Args[1],iofs->io_Args[2]);
  665.         break;
  666.  
  667.     case FSA_EXAMINE_ALL:
  668.         error=examine_all((struct filehandle *)iofs->IOFS.io_Unit,
  669.               (struct ExAllData *)iofs->io_Args[0],
  670.               iofs->io_Args[1],iofs->io_Args[2]);
  671.         break;
  672.  
  673.     default:
  674.         error=ERROR_NOT_IMPLEMENTED;
  675.         break;
  676.     }
  677.  
  678.     /* Set error code */
  679.     iofs->io_DosError=error;
  680.  
  681.     /* If the quick bit is not set send the message to the port */
  682.     if(!(iofs->IOFS.io_Flags&IOF_QUICK))
  683.     ReplyMsg(&iofs->IOFS.io_Message);
  684.  
  685.     /* Trigger a rescedule every now and then */
  686.     if(SysBase->TaskReady.lh_Head->ln_Pri==SysBase->ThisTask->tc_Node.ln_Pri&&
  687.        SysBase->TDNestCnt<0&&SysBase->IDNestCnt<0)
  688.     {
  689.     SysBase->ThisTask->tc_State=TS_READY;
  690.     Enqueue(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
  691.     Switch();
  692.     }
  693.  
  694.     __AROS_FUNC_EXIT
  695. }
  696.  
  697. __AROS_LH1(LONG, abortio,
  698.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  699.        struct emulbase *, emulbase, 6, emul_handler)
  700. {
  701.     __AROS_FUNC_INIT
  702.     /* Everything already done. */
  703.     return 0;
  704.     __AROS_FUNC_EXIT
  705. }
  706.  
  707. static const char end=0;
  708.